//////////////////////////////////////
// Fast Container Library           //
// MIT License - Copyright (c) 2012 //
//////////////////////////////////////

#pragma once

#include "common.h"
#include "algobase.h"
#include "iterator.h"

FC_NAMESPACE_BEGIN


template <class T, size_t N>
struct static_array
{
public:
	typedef size_t									size_type;
	typedef T										value_type;
	typedef T*										pointer;
	typedef const T*								const_pointer;
	typedef T&										reference;
	typedef const T&								const_reference;
	typedef pointer									iterator;
	typedef const_pointer							const_iterator;
	typedef fc::reverse_iterator<iterator>			reverse_iterator;
	typedef fc::reverse_iterator<const_iterator>	const_reverse_iterator;
	typedef ptrdiff_t								difference_type;
	typedef static_array<T, N>						this_type;

	enum : size_type
	{
		array_size = N,
		array_size_n_bytes = array_size * sizeof(T)
	};

	//aggregate type

	size_t size() const { return N; }

	iterator begin()					{ return &m_data[0]; }
	const_iterator begin() const		{ return &m_data[0]; }
	iterator end()						{ return begin() + N; }
	const_iterator end() const			{ return begin() + N; }
	reverse_iterator rend()				{ return reverse_iterator(begin()); }
	const_reverse_iterator rend() const	{ return const_reverse_iterator(begin()); }
	reverse_iterator rbegin()			{ return reverse_iterator(end()); }
	const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }

	pointer data()					{ return &m_data[0]; }
	const_pointer data() const		{ return &m_data[0]; }
	reference front()				{ return m_data[0]; }
	const_reference front() const	{ return m_data[0]; }
	reference back()				{ return m_data[N - 1]; }
	const_reference back() const	{ return m_data[N - 1]; }

	reference operator []( size_t i ) { return m_data[i]; }
	const_reference operator []( size_t i ) const { return m_data[i]; }

	reference at( size_t i )
	{
		FC_ASSERT(i < size());
		return m_data[i];
	}

	const_reference at( size_t i ) const
	{
		FC_ASSERT(i < size());
		return m_data[i];
	}

	void assign( const value_type& value )
	{
		fc::fill_n( begin(), size(), value );
	}

    void swap( this_type& x )
    {
        fc::swap_ranges(&m_data[0], &m_data[N], &x.m_data[0]);
    }

	bool iterator_is_valid( const_iterator it ) const
	{
		return (it >= begin() && it <= end());
	}

	T m_data[N ? N : 1];
};


template <class T, size_t N> inline
	bool operator ==( const static_array<T, N>& a, const static_array<T, N>& b )
	{
		return( &a == &b || fc::equal(a.begin(), a.end(), b.begin()) );
	}

template <class T, size_t N> inline
	bool operator !=( const static_array<T, N>& a, const static_array<T, N>& b )
	{
		return !(a == b);
	}


FC_NAMESPACE_END
